package zhou.chs.p7_1;


import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import weiqian.hardware.CustomFunctions;

public class MainActivity extends AppCompatActivity implements AdapterView.OnItemLongClickListener,AdapterView.OnItemSelectedListener{
    //声明控件
    TextView tvt; //显示所内温湿度
    TextView tvd; //显示日期
    TextView tva; //显示报警信息
    TextView tvs; //显示选中回路显示其曲线
    ListView lvh; //显示各回路实时温度
    Spinner spd; //曲线部位选择，分进线、开关、出线3个部位，同时显示3相
    ImageView img; //显示曲线
    SerialPort serialPort,serialPort2;   //串口
    //声明变量
    private Date now; //日期
    private SimpleDateFormat myDate;   //日期
    private MyAdapter mAdapter;         //适配器
    private ReadThread mReadThread;	//读取线程
    private ReadThread2 mReadThread2;	//读取线程
    private Handler myhandler;       //信息通道
    private Timer mTimer;   //定时器
    int tn;   //定时计数
    int en=0;   //开机延时显示
    int smax;                          //回路数
    int tmax=60;                          //报警温度上限
    int ttc=20;                            //与同部位平均温度之差报警值
    String[] strhl = new String[120];    //回路名称
    int[] t1 = new int[120];            //温度值1-9
    int[] t2 = new int[120];
    int[] t3 = new int[120];
    int[] t4 = new int[120];
    int[] t5 = new int[120];
    int[] t6 = new int[120];
    int[] t7 = new int[120];
    int[] t8 = new int[120];
    int[] t9 = new int[120];
    int[] t10 = new int[120];   //通信超时计数
    int[] t11 = new int[120];   //异常标志，0-正常  1-温度异常  2-电池电压低
    int[] bt = new int[120];    //电池电压
    int[] ttn = new int[120];   //回路通信地址
    String shows; //选中回路名称
    int zn; //部位选择：0-进线  1-开关   2-出线
    byte[] rbuf1 = new byte[32];    //COM1接收缓冲区
    byte[] rbuf2 = new byte[32];    //COM2接收缓冲区
    private int newh,oldh;  //原小时，每小时判断一次通信情况，更新数据库，检查过期数据删除
    static final String db_name="ts";  //数据库名称
    static final String tb_name="tb";   //温度数据表
    static final String ab_name="ab";   //报警信息表
    SQLiteDatabase db; //数据库
    String day1,day2,day3;  //今天、昨天、前天日期值
    int tm;     //温度数据组数
    int[] tba = new int[128];            //温度曲线缓冲区a
    int[] tbb = new int[128];            //温度曲线缓冲区b
    int[] tbc = new int[128];            //温度曲线缓冲区c
    private Bitmap bitmap;      //图片
    private Canvas canvas;      //画布
    private int myX;        //画布宽度
    private int myY;        //画布高度
    private Paint paint;        //画笔
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        CustomFunctions.FullScreenSticky(getWindow()); //全屏模式
        //控件实例化
        tvt=(TextView) findViewById(R.id.idtv1);
        tvd=(TextView) findViewById(R.id.idtv3);
        tva=(TextView) findViewById(R.id.idtv4);
        tvs=(TextView) findViewById(R.id.idtv5);
        lvh=(ListView) findViewById(R.id.idlv);
        spd=(Spinner) findViewById(R.id.spinner);
        img=(ImageView) findViewById(R.id.idimg);
        tva.setMovementMethod(ScrollingMovementMethod.getInstance());   //文本可滚动
        datin();    //导入回路数据
        spd.setOnItemSelectedListener(this);  //测温部位选项监听注册
        mAdapter = new MyAdapter(this);//得到1个MyAdapter对象
        lvh.setAdapter(mAdapter);        //为ListView绑定Adapter
        lvh.setOnItemLongClickListener(this); //注册列表选择监听事件
        serialPort = new SerialPort();  //串口1
        serialPort2 = new SerialPort(); //串口2
        myhandler = new MyHandler();        //实例化Handler，用于进程间的通信
        //打开2个串口，参数都是9600,n,8,1
        serialPort.open("COM1",9600, 8, "N", 1);
        serialPort2.open("COM2",9600, 8, "N", 1);
        mReadThread = new ReadThread();
        mReadThread.start();    //启动串口1接收数据线程
        mReadThread2 = new ReadThread2();
        mReadThread2.start();   //启动串口2接收数据线程
        //数据库操作
        db=openOrCreateDatabase(db_name, Context.MODE_PRIVATE,null);
        String createTable="CREATE TABLE IF NOT EXISTS " + tb_name + "(mdate VARCHAR(20),mtime VARCHAR(10),name VARCHAR(32),t1 INTEGER,t2 INTEGER,t3 INTEGER,t4 INTEGER,t5 INTEGER,t6 INTEGER,t7 INTEGER,t8 INTEGER,t9 INTEGER)";
        db.execSQL(createTable);
        createTable="CREATE TABLE IF NOT EXISTS " + ab_name + "(mdate VARCHAR(20),name VARCHAR(32),msg VARCHAR(64))";
        db.execSQL(createTable);
        //初始化日期与时间
        now = new Date();
        String t = String.format("%tR",now);
        String[] tt = t.split(":");
        newh=Integer.parseInt(tt[0]);
        oldh=newh;
        myDate = new SimpleDateFormat("yyyy-MM-dd");
        day1 = myDate.format(new Date(System.currentTimeMillis()));  //当前日期
        day2 = myDate.format(new Date(System.currentTimeMillis()-24*3600000));  //昨天日期
        day3 = myDate.format(new Date(System.currentTimeMillis()-48*3600000));  //前天日期
        shows = strhl[0];   //默认显示第一个回路的温度曲线
        tvs.setText(shows);
        mTimer = new Timer();         //新建Timer
        mTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                tn++;                   //每秒加1
                Message msg1 = myhandler.obtainMessage();
                msg1.what = 1;
                myhandler.sendMessage(msg1);
            }
        }, 1000, 1000);     //延时1000ms，然后每隔1000ms发送消息
    }
    // 添加温度记录
    private void addTmp(String mdate, String mtime,String name, int tt1, int tt2, int tt3, int tt4, int tt5, int tt6, int tt7, int tt8, int tt9) {
        ContentValues cv=new ContentValues(9); //
        cv.put("mdate", mdate);
        cv.put("mtime", mtime);
        cv.put("name", name);
        cv.put("t1", tt1);
        cv.put("t2", tt2);
        cv.put("t3", tt3);
        cv.put("t4", tt4);
        cv.put("t5", tt5);
        cv.put("t6", tt6);
        cv.put("t7", tt7);
        cv.put("t8", tt8);
        cv.put("t9", tt9);
        db.insert(tb_name, null, cv);
    }
    // 添加并显示报警记录
    private void addAlm(String mdate, String name, String strm) {
        ContentValues cv=new ContentValues(3);
        cv.put("mdate", mdate);
        cv.put("name", name);
        cv.put("msg", strm);
        db.insert(ab_name, null, cv);

        Cursor p=db.rawQuery("SELECT * FROM " + ab_name, null);
        if (p.getCount()>0){
            String str="共有"+p.getCount()+"条报警记录\n";
            p.moveToLast();                     //指针移到起始记录
            do{                                 //将报警记录赋值给字符串
                str+=p.getString(0) + "  " + p.getString(1)  + "  " + p.getString(2) + "\n";
            } while(p.moveToPrevious());   //指针移到下一个记录
            tva.setText(str);   //显示报警记录
        }
        p.close();
    }
    @Override  //长按某回路则显示该回路温度曲线
    public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
        shows = strhl[i];
        tvs.setText(shows);
        if(en>0) Show();
        return false;
    }
    @Override   //选择要显示温度曲线的测点部位
    public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
        zn=i;
        if(en>0) Show();
        CustomFunctions.FullScreenSticky(getWindow()); //全屏模式
    }
    @Override
    public void onNothingSelected(AdapterView<?> adapterView) {
        CustomFunctions.FullScreenSticky(getWindow()); //全屏模式
    }
    // COM1读取数据的线程
    private class ReadThread extends Thread {
        @Override
        public void run() {
            super.run();
            byte[] buff = new byte[32]; //串口接收临时缓冲区
            while(true){
                try {
                    int n = serialPort.read(buff,32,100);
                    if(n > 0) {
                        Message msg = myhandler.obtainMessage();
                        msg.what = 2;
                        for (int i=0;i<n;i++){
                            rbuf1[i] = buff[i];
                        }   //将临时缓冲区数据转移到串口1接收缓冲区
                        msg.obj=n;
                        myhandler.sendMessage(msg); //发消息：串口1收到数据
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    // COM2读取数据的线程
    private class ReadThread2 extends Thread {
        @Override
        public void run() {
            super.run();
            byte[] buf = new byte[32]; //串口接收临时缓冲区
            while(true){
                try {
                    int n = serialPort2.read(buf,32,100);
                    if(n > 0) {
                        for (int i=0;i<n;i++){
                            rbuf2[i] = buf[i];
                        }   //将临时缓冲区数据转移到串口2接收缓冲区
                        Message msg = myhandler.obtainMessage();
                        msg.what = 3;
                        myhandler.sendMessage(msg);  //发消息：串口2收到数据
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    //在主线程处理Handler传回来的message
    class MyHandler extends Handler {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:   //定时
                    now = new Date();
                    String t = String.format("%tR",now);
                    tvd.setText(String.format("%tF",now) + "  " + t);
                    String[] tt = t.split(":");
                    newh=Integer.parseInt(tt[0]);
                    if(newh!=oldh) {
                        myDate = new SimpleDateFormat("yyyy-MM-dd");
                        day1 = myDate.format(new Date(System.currentTimeMillis()));  //当前日期
                        day2 = myDate.format(new Date(System.currentTimeMillis()-24*3600000));  //昨天日期
                        day3 = myDate.format(new Date(System.currentTimeMillis()-48*3600000));  //前天日期
                        db.delete(ab_name, "mdate<?", new String[]{day3});  //删除3天前报警记录
                        db.delete(tb_name, "mdate<?", new String[]{day3});  //删除3天前温度记录
                        for (int j = 0; j < smax; j++) {    //通信中断判断
                            t10[j]++;
                            if (t10[j] > 3) {
                                t10[j] = 5;
                                db.delete(ab_name, "name=?", new String[]{strhl[j]});
                                addAlm(day1, strhl[j], "通信中断！");
                            }
                            //温度记录
                            addTmp(day1, tt[0], strhl[j], t1[j], t2[j], t3[j], t4[j], t5[j], t6[j], t7[j], t8[j], t9[j]);
                            if(en>0) Show();
                        }
                    }
                    oldh=newh;
                    if(tn>5){   //5s采集一次温湿度
                        tn=0;
                        en=1;
                        byte[] tbuf={(byte)0x01,(byte)0x03,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x02,
                                (byte)0xC4,(byte)0x0B};
                        serialPort2.write(tbuf,8); //发送读取温湿度数据
                    }
                    break;
                case 2:   //COM1收到数据
                    if(rbuf1[1]==3) {
                        int n = 0;
                        while ((ttn[n] != (rbuf1[0] & 0xFF)) && (n < smax)) {
                            n++;
                        }
                        if (n >= smax) break;
                        int m = 0;
                        for (int i = 0; i < 9; i++) {
                            if (rbuf1[3 + i] > tmax) m = 1;
                        }
                        int tp=(rbuf1[3]+rbuf1[4]+rbuf1[5])/3;
                        for (int i = 0; i < 3; i++) if((rbuf1[3+i]-tp)>ttc) m=1;
                        tp=(rbuf1[6]+rbuf1[7]+rbuf1[8])/3;
                        for (int i = 0; i < 3; i++) if((rbuf1[6+i]-tp)>ttc) m=1;
                        tp=(rbuf1[9]+rbuf1[10]+rbuf1[11])/3;
                        for (int i = 0; i < 3; i++) if((rbuf1[9+i]-tp)>ttc) m=1;
                        t11[n] = 0;
                        if (m > 0) {   //温度异常报警
                            db.delete(ab_name, "name=?", new String[]{strhl[n]});
                            addAlm(day1, strhl[n], "温度异常！");
                            t11[n] = 1;
                        }
                        t1[n] = rbuf1[3];
                        t2[n] = rbuf1[4];
                        t3[n] = rbuf1[5];
                        t4[n] = rbuf1[6];
                        t5[n] = rbuf1[7];
                        t6[n] = rbuf1[8];
                        t7[n] = rbuf1[9];
                        t8[n] = rbuf1[10];
                        t9[n] = rbuf1[11];
                        t10[n] = 0;  //通信中断计数清零
                        bt[n] = rbuf1[12];
                        mAdapter.notifyDataSetChanged();  //刷新列表显示
                        if(bt[n] < 36) {      //电池电压低报警
                            db.delete(ab_name,"name=?",new String[]{strhl[n]});
                            addAlm(day1,strhl[n],"电池电压低！");
                            t11[n] = 2; //
                        }
                    }
                    break;
                case 3:   //COM2收到数据
                    if((rbuf2[1]==3)&&(rbuf2[2]==4)) {
                        if (rbuf2[3] == 0x80) tvt.setText("");
                        else {      //处理并显示数据
                            int m = (rbuf2[3] << 8) | (rbuf2[4] & 0xFF);
                            String s= "室内温度：" + String.format("%.1f", (float) m / 10) + "℃  ";
                            m = (rbuf2[5] << 8) | (rbuf2[6] & 0xFF);
                            s = s + " 湿度：" + String.format("%.1f", (float) m / 10) + "%rh";
                            tvt.setText(s);  //显示温湿度数据
                        }
                    }
                    break;
            }
        }
    }
    //导入数据
    public void datin() {
        int m=0;
        String str="";
        //打开文件夹“Documents”中的“dat.csv”文件
        File file = new File(Environment.getExternalStoragePublicDirectory
                (Environment.DIRECTORY_DOCUMENTS), "dat.csv");
        try {   //将GBK格式转为UTF-8格式
            InputStreamReader inreader =
                    new InputStreamReader(new FileInputStream(file), "GBK");
            BufferedReader reader = new BufferedReader(inreader);
            str = reader.readLine();  //标题行忽略
            do {
                str = reader.readLine(); //取记录
                String[] strdat = str.split(",");  //根据","分隔出字段插入到数据表
                strhl[m]=strdat[0];  //获得回路名称
                ttn[m]=Integer.parseInt(strdat[1]);  //获得回路的通信地址
                m++;
                smax=m; //获得回路总数
            }
            while (!str.equals(null));
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //存放item.xml中的控件
    public final class ViewHolder{
        public TextView tv30,tv31,tv32,tv33,tv34,tv35,tv36,tv37,tv38,tv39,tv40;
    }
    //构造新的适配器
    private class MyAdapter extends BaseAdapter {
        private LayoutInflater mInflater;   //得到一个LayoutInfalter对象用来导入布局
        public MyAdapter(Context context) {  //构造函数
            this.mInflater = LayoutInflater.from(context);
        }
        @Override   //返回数组的长度
        public int getCount() {
            return smax;
        }
        @Override
        public Object getItem(int position) {
            return null;
        }
        @Override
        public long getItemId(int position) { return 0; }
        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView == null) {
                convertView = mInflater.inflate(R.layout.item,null);
                holder = new ViewHolder();
                //得到各个控件的对象
                holder.tv30 = (TextView) convertView.findViewById(R.id.idtv30);
                holder.tv31 = (TextView) convertView.findViewById(R.id.idtv31);
                holder.tv32 = (TextView) convertView.findViewById(R.id.idtv32);
                holder.tv33 = (TextView) convertView.findViewById(R.id.idtv33);
                holder.tv34 = (TextView) convertView.findViewById(R.id.idtv34);
                holder.tv35 = (TextView) convertView.findViewById(R.id.idtv35);
                holder.tv36 = (TextView) convertView.findViewById(R.id.idtv36);
                holder.tv37 = (TextView) convertView.findViewById(R.id.idtv37);
                holder.tv38 = (TextView) convertView.findViewById(R.id.idtv38);
                holder.tv39 = (TextView) convertView.findViewById(R.id.idtv39);
                holder.tv40 = (TextView) convertView.findViewById(R.id.idtv40);
                convertView.setTag(holder);//绑定ViewHolder对象
            }
            else{
                holder = (ViewHolder)convertView.getTag();//取出ViewHolder对象
            }
            //设置TextView显示的内容，即我们存放在数组中的数据
            holder.tv30.setText(strhl[position]);
            holder.tv31.setText(Integer.toString(t1[position]));
            holder.tv32.setText(Integer.toString(t2[position]));
            holder.tv33.setText(Integer.toString(t3[position]));
            holder.tv34.setText(Integer.toString(t4[position]));
            holder.tv35.setText(Integer.toString(t5[position]));
            holder.tv36.setText(Integer.toString(t6[position]));
            holder.tv37.setText(Integer.toString(t7[position]));
            holder.tv38.setText(Integer.toString(t8[position]));
            holder.tv39.setText(Integer.toString(t9[position]));
            holder.tv40.setText(String.format("%.1f",(float)bt[position]/10));
            holder.tv30.setBackgroundColor(0);
            //温度超限或电池电压低时，回路名称背景色变为红色
            if(t11[position] > 0) holder.tv30.setBackgroundColor(Color.RED);
            //通信中断时，回路名称背景色变为红色
            if(t10[position] > 3) holder.tv30.setBackgroundColor(Color.YELLOW);
            return convertView;
        }
    }
    //显示波形
    public void Show() {
        String[] st = new String[]{"t1","t2","t3"};  //默认选择进线部位测点温度
        if(zn==1) st = new String[]{"t4","t5","t6"};  //选择开关部位测点温度
        if(zn==2) st = new String[]{"t7","t8","t9"};    //选择出线部位测点温度
        Cursor p = db.query(tb_name, st, null, null, null, null, null);  //通过
        tm = p.getCount();  //获得记录总数
        if (tm > 0) {
            if (tm > 72) tm = 72;
            p.moveToFirst();  //移动指针到第一条
            for (int i = 0; i < tm; i++) {  //将对应温度赋值给显示曲线缓冲区
                tba[i] = p.getInt(0);
                tbb[i] = p.getInt(1);
                tbc[i] = p.getInt(2);
                p.moveToNext(); //移动指针到下一条
            }
        }
        p.close();
        myX=img.getWidth();
        myY=img.getHeight();
        if (bitmap == null) {                //创建一个新的bitmap对象，宽、高使用界面布局中ImageView对象的宽、高
            bitmap = Bitmap.createBitmap(myX, myY, Bitmap.Config.RGB_565);
        }
        canvas = new Canvas(bitmap);        //根据bitmap对象创建一个画布
        canvas.drawColor(Color.WHITE);      //设置画布背景色为白色    //canvas.drawRect(0,0,736,512,paint);
        paint = new Paint();                //创建一个画笔对象

        paint.setStrokeWidth(8);            //设置画笔的线条粗细为2磅
        paint.setColor(Color.BLACK);         //画外框
        canvas.drawLine(0, 0, myX, 0,paint);
        canvas.drawLine(0, myY,myX, img.getHeight(),paint);
        canvas.drawLine(0, 0, 0, myY,paint);
        canvas.drawLine(myX, 0, myX, myY,paint);

        paint.setStrokeWidth(2);            //设置画笔的线条粗细为2磅
        paint.setColor(Color.GRAY);         //画背景网格
        for(int i=1;i<5;i++){
            canvas.drawLine(0,i*myY/5,myX,i*myY/5,paint);
        }
        for(int i=1;i<3;i++){
            canvas.drawLine(i*myX/3,0,i*myX/3,myY,paint);
        }
        //画温度坐标
        canvas.drawText(String.format("%d",60),10,myY/5-10,paint);
        canvas.drawText(String.format("%d",40),10,2*myY/5-10,paint);
        canvas.drawText(String.format("%d",20),10,3*myY/5-10,paint);
        canvas.drawText(String.format("%d",0),10,4*myY/5-10,paint);
        canvas.drawText(String.format("%d",-20),10,myY-10,paint);
        paint.setColor(Color.YELLOW); //画A相温度曲线，黄色
        for(char i=1;i<tm;i++){
            canvas.drawLine((i-1)*myX/72, myY-(tba[i-1]+20)*myY/100, i*myX/72,myY-(tba[i]+20)*myY/100,paint);
        }
        paint.setColor(Color.GREEN);			//画B相温度曲线，绿色
        for(char i=1;i<tm;i++){
            canvas.drawLine((i-1)*myX/72, myY-(tbb[i-1]+20)*myY/100, i*myX/72,myY-(tbb[i]+20)*myY/100,paint);
        }
        paint.setColor(Color.RED);			//画C相温度曲线，红色
        for(char i=1;i<tm;i++){
            canvas.drawLine((i-1)*myX/72, myY-(tbc[i-1]+20)*myY/100, i*myX/72,myY-(tbc[i]+20)*myY/100,paint);
        }
        img.setImageBitmap(bitmap);     //在ImageView中显示bitmap
    }
    //程序暂停前关闭定时器
    public void onPause() {
        super.onPause();
        mTimer.cancel();
    }
}
